<template>
  <div class="bpmn-container">
    <!-- 工具栏 -->
    <div class="toolbar">
      <div class="tool-group">
        <button class="tool-button" @click="saveDiagram">
          <i class="fas fa-save"></i>
          保存
        </button>
        <button class="tool-button" @click="downloadDiagram">
          <i class="fas fa-download"></i>
          下载
        </button>
        <button class="tool-button" @click="openFile">
          <i class="fas fa-folder-open"></i>
          打开
        </button>
        <input
          type="file"
          ref="fileInput"
          style="display: none"
          @change="handleFileSelect"
          accept=".bpmn,.xml"
        />
      </div>
      <div class="tool-group">
        <button class="tool-button" @click="zoomIn">
          <i class="fas fa-search-plus"></i>
        </button>
        <button class="tool-button" @click="zoomOut">
          <i class="fas fa-search-minus"></i>
        </button>
        <button class="tool-button" @click="resetZoom">
          <i class="fas fa-compress-arrows-alt"></i>
        </button>
      </div>
    </div>

    <!-- BPMN画布 -->
    <div class="canvas-container" ref="canvasContainer">
      <div class="canvas" ref="canvas"></div>
    </div>

    <!-- 属性面板 -->
    <div class="properties-panel" ref="propertiesPanel">
      <div class="panel-header">
        <h3>属性设置</h3>
      </div>
      <div class="panel-content">
        <template v-if="selectedElement">
          <div class="property-group">
            <h4>基本信息</h4>
            <div class="property-item">
              <label>ID</label>
              <input type="text" v-model="selectedElement.id" @change="updateProperty('id')">
            </div>
            <div class="property-item">
              <label>名称</label>
              <input type="text" v-model="selectedElement.name" @change="updateProperty('name')">
            </div>
          </div>
          <div class="property-group">
            <h4>执行设置</h4>
            <div class="property-item">
              <label>执行人</label>
              <input type="text" v-model="selectedElement.assignee" @change="updateProperty('assignee')">
            </div>
            <div class="property-item">
              <label>候选人</label>
              <input type="text" v-model="selectedElement.candidateUsers" @change="updateProperty('candidateUsers')">
            </div>
          </div>
        </template>
      </div>
    </div>
  </div>
</template>

<script setup>
import { ref, onMounted, onUnmounted } from 'vue'
import BpmnModeler from 'bpmn-js/lib/Modeler'
import 'bpmn-js/dist/assets/diagram-js.css'
import 'bpmn-js/dist/assets/bpmn-font/css/bpmn.css'
import minimapModule from 'diagram-js-minimap'
import 'diagram-js-minimap/assets/diagram-js-minimap.css'

// BPMN建模器实例
let modeler = null
const canvas = ref(null)
const selectedElement = ref(null)

// 初始化BPMN建模器
const initBpmnModeler = () => {
  modeler = new BpmnModeler({
    container: canvas.value,
    additionalModules: [
      minimapModule
    ],
    propertiesPanel: {
      parent: '#properties-panel'
    }
  })

  // 监听元素选择事件
  modeler.on('selection.changed', (e) => {
    const selection = e.newSelection
    if (selection.length) {
      const element = selection[0]
      selectedElement.value = {
        id: element.id,
        name: element.businessObject.name || '',
        assignee: element.businessObject.assignee || '',
        candidateUsers: element.businessObject.candidateUsers || ''
      }
    } else {
      selectedElement.value = null
    }
  })

  // 创建新的图表
  createNewDiagram()
}

// 创建新的图表
const createNewDiagram = async () => {
  try {
    const result = await modeler.createDiagram()
    console.log('创建新图表成功', result)
  } catch (err) {
    console.error('创建新图表失败', err)
  }
}

// 保存图表
const saveDiagram = async () => {
  try {
    const { xml } = await modeler.saveXML({ format: true })
    console.log('保存的XML', xml)
    // 这里可以调用API保存XML
  } catch (err) {
    console.error('保存失败', err)
  }
}

// 下载图表
const downloadDiagram = async () => {
  try {
    const { xml } = await modeler.saveXML({ format: true })
    const blob = new Blob([xml], { type: 'application/xml' })
    const url = window.URL.createObjectURL(blob)
    const a = document.createElement('a')
    a.href = url
    a.download = 'diagram.bpmn'
    a.click()
    window.URL.revokeObjectURL(url)
  } catch (err) {
    console.error('下载失败', err)
  }
}

// 打开文件
const fileInput = ref(null)
const openFile = () => {
  fileInput.value.click()
}

// 处理文件选择
const handleFileSelect = (event) => {
  const file = event.target.files[0]
  if (file) {
    const reader = new FileReader()
    reader.onload = async (e) => {
      const xml = e.target.result
      try {
        await modeler.importXML(xml)
      } catch (err) {
        console.error('导入失败', err)
      }
    }
    reader.readAsText(file)
  }
}

// 缩放控制
const zoomIn = () => {
  modeler.get('canvas').zoom(modeler.get('canvas').zoom() + 0.1)
}

const zoomOut = () => {
  modeler.get('canvas').zoom(modeler.get('canvas').zoom() - 0.1)
}

const resetZoom = () => {
  modeler.get('canvas').zoom('fit-viewport')
}

// 更新属性
const updateProperty = (property) => {
  const modeling = modeler.get('modeling')
  const element = modeler.get('selection').get()[0]
  
  if (element && selectedElement.value) {
    const newValue = selectedElement.value[property]
    modeling.updateProperties(element, {
      [property]: newValue
    })
  }
}

onMounted(() => {
  initBpmnModeler()
})

onUnmounted(() => {
  if (modeler) {
    modeler.destroy()
  }
})
</script>

<style scoped>
.bpmn-container {
  width: 100%;
  height: 100vh;
  display: grid;
  grid-template-rows: auto 1fr;
  grid-template-columns: 1fr 300px;
  background-color: var(--theme-bg, #f8fafc);
}

.toolbar {
  grid-column: 1 / -1;
  padding: 8px 16px;
  background-color: var(--theme-container-bg, #ffffff);
  border-bottom: 1px solid var(--theme-border-color, #e2e8f0);
  display: flex;
  gap: 16px;
}

.tool-group {
  display: flex;
  gap: 8px;
}

.tool-button {
  padding: 8px 12px;
  background-color: var(--theme-secondary-bg, #f1f5f9);
  border: 1px solid var(--theme-border-color, #e2e8f0);
  border-radius: 4px;
  cursor: pointer;
  display: flex;
  align-items: center;
  gap: 6px;
  transition: all 0.2s;
}

.tool-button:hover {
  background-color: var(--theme-hover-bg, #e2e8f0);
}

.canvas-container {
  position: relative;
  overflow: hidden;
  background-color: var(--theme-bg, #ffffff);
}

.canvas {
  width: 100%;
  height: 100%;
}

.properties-panel {
  background-color: var(--theme-container-bg, #ffffff);
  border-left: 1px solid var(--theme-border-color, #e2e8f0);
  overflow-y: auto;
}

.panel-header {
  padding: 16px;
  border-bottom: 1px solid var(--theme-border-color, #e2e8f0);
}

.panel-header h3 {
  margin: 0;
  color: var(--theme-text-color, #1e293b);
}

.panel-content {
  padding: 16px;
}

.property-group {
  margin-bottom: 20px;
}

.property-group h4 {
  margin: 0 0 12px;
  color: var(--theme-text-color, #1e293b);
  font-size: 14px;
}

.property-item {
  margin-bottom: 12px;
}

.property-item label {
  display: block;
  margin-bottom: 4px;
  color: var(--theme-text-color, #64748b);
  font-size: 12px;
}

.property-item input {
  width: 100%;
  padding: 6px 8px;
  border: 1px solid var(--theme-border-color, #e2e8f0);
  border-radius: 4px;
  font-size: 14px;
}

.property-item input:focus {
  outline: none;
  border-color: var(--theme-primary-color, #3b82f6);
}

/* 暗色主题 */
@media (prefers-color-scheme: dark) {
  .bpmn-container {
    background-color: var(--theme-bg, #0f172a);
  }

  .toolbar,
  .properties-panel {
    background-color: var(--theme-container-bg, #1e293b);
    border-color: var(--theme-border-color, #334155);
  }

  .tool-button {
    background-color: var(--theme-secondary-bg, #334155);
    border-color: var(--theme-border-color, #475569);
    color: var(--theme-text-color, #e2e8f0);
  }

  .tool-button:hover {
    background-color: var(--theme-hover-bg, #475569);
  }

  .panel-header {
    border-color: var(--theme-border-color, #334155);
  }

  .panel-header h3,
  .property-group h4 {
    color: var(--theme-text-color, #e2e8f0);
  }

  .property-item label {
    color: var(--theme-text-color, #94a3b8);
  }

  .property-item input {
    background-color: var(--theme-secondary-bg, #334155);
    border-color: var(--theme-border-color, #475569);
    color: var(--theme-text-color, #e2e8f0);
  }
}
</style> 